/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {
    ArkFile,
    ts,
} from 'arkanalyzer';
import { Rule } from '../../Index';
import { BaseChecker, BaseMetaData } from '../BaseChecker';
import { Defects } from '../../Index';
import {
    FileMatcher,
    MatcherCallback,
    MatcherTypes,
} from '../../Index';
import { RuleListUtil } from "../../utils/common/DefectsList";
import { IssueReport } from '../../model/Defects';
import { RuleFix } from '../../model/Fix';
type Options = [
    {
        int32Hint: boolean;
    }
];

export class SpaceInfixOpsCheck implements BaseChecker {
    codeFix?(arkFile: ArkFile, fixKey: string): boolean {
        throw new Error('Method not implemented.');
    }
    public issues: IssueReport[] = [];
    public rule: Rule;
    public defects: Defects[] = [];
    public sourceFile: ts.SourceFile;
    public firstDealFlag: boolean = false;
    public countTypeColumnFlag: number = 0;
    public firstEqualsFlag: boolean = false;
    public isConditionalTypeFlag: boolean = false;
    public specialTypeAliasDeclarationFlag: boolean = false;
    private defaultOptions: Options = [
        { int32Hint: false },
    ];
    public metaData: BaseMetaData = {
        severity: 2,
        ruleDocPath: 'docs/space-infix-ops-check.md',
        description: 'Require spacing around infix operators',
    };

    private fileMatcher: FileMatcher = {
        matcherType: MatcherTypes.FILE,
    };

    public registerMatchers(): MatcherCallback[] {
        const matchFileCb: MatcherCallback = {
            matcher: this.fileMatcher,
            callback: this.check
        }
        return [matchFileCb];
    }

    /**
     * 检测代码中的 space-infix-ops 规则错误
     * @param code 需要检测的代码字符串
     * @param int32Hint 是否强制要求 |0 操作符周围有空格
     */
    private checkSpaceInfixOps(code: string, int32Hint: boolean) {
        this.sourceFile = ts.createSourceFile('test.ts', code, ts.ScriptTarget.Latest, true);
        const errors: { line: number; character: number; message: string, node: ts.Node, optionValue: boolean }[] = [];

        const checkOperatorSpacing = (
            operator: string,
            start: number,
            end: number,
            node: ts.Node,
            isInt32Hint: boolean = false,
            allowLeftNewline: boolean = false // 新增参数
        ) => {
            if (isInt32Hint && int32Hint) return;

            // 排除箭头函数的等号（=>）
            if (operator === '=' && code.slice(end, end + 1) === '>') return;

            const textBefore = code.slice(Math.max(0, start - 1), start);
            const textAfter = code.slice(end, end + 1);
            const validBefore = allowLeftNewline ?
                /[\s\r\n]/.test(textBefore) :
                /^[ \t]$/.test(textBefore);
            // 增加特殊字符过滤
            const validAfter = operator === ':' ?
                /[\s\r\n]/.test(textAfter) :  // 允许冒号后换行
                /[\s\r\n]/.test(textAfter) && !/[.,;)]/.test(textAfter);

            if (!validBefore || !validAfter) {
                const { line, character } = this.sourceFile.getLineAndCharacterOfPosition(start);
                errors.push({
                    line: line + 1,
                    character: character + 1,
                    message: `Operator '${operator}' must be spaced.`,
                    node: node,
                    optionValue: int32Hint
                });
            }
        }

        // 带上下文处理方法
        const handleUnionOrIntersectionTypeWithContext = (typeNode: ts.UnionTypeNode | ts.IntersectionTypeNode, isInterfaceContext: boolean, node: ts.Node, optionValue: boolean) => {
            const operator = ts.isUnionTypeNode(typeNode) ? '|' : '&';

            typeNode.types.forEach((type, index) => {
                if (index === 0) return;

                const prevType = typeNode.types[index - 1];
                const startSearchPos = prevType.getEnd();
                const endSearchPos = type.getStart();
                const operatorRange = code.slice(startSearchPos, endSearchPos);

                const operatorPos = operatorRange.indexOf(operator);
                if (operatorPos === -1) return;

                const opStart = startSearchPos + operatorPos;
                const opEnd = opStart + 1;

                // 接口属性特殊规则：左侧必须空格（不允许换行）
                const textBefore = code[opStart - 1] || '';
                const textAfter = code[opEnd] || '';

                const validBefore = isInterfaceContext ?
                    textBefore === ' ' :  // 接口属性严格要求空格
                    /[\s\r\n]/.test(textBefore);  // 其他场景允许换行

                const validAfter = /[\s\r\n]/.test(textAfter);

                if (!validBefore || !validAfter) {
                    const { line, character } = this.sourceFile.getLineAndCharacterOfPosition(opStart);
                    errors.push({
                        line: line + 1,
                        character: character + 1,
                        message: `Operator '${operator}' must be spaced.`,
                        node: node,
                        optionValue: int32Hint
                    });
                }
            });
        }

        // 统一处理联合/交叉类型操作符
        const handleUnionOrIntersectionType = (typeNode: ts.UnionTypeNode | ts.IntersectionTypeNode, node: ts.Node, optionValue: boolean) => {
            const operator = ts.isUnionTypeNode(typeNode) ? '|' : '&';

            // 首字符操作符检测
            if (typeNode.types.length > 0) {
                const firstType = typeNode.types[0];
                const startPos = typeNode.getStart();
                const firstTypeStart = firstType.getStart();
                const leadingRange = code.slice(startPos, firstTypeStart);

                if (leadingRange.includes(operator)) {
                    const opStart = startPos + leadingRange.indexOf(operator);
                    checkOperatorSpacing(operator, opStart, opStart + 1, node, false, true);
                }
            }
            typeNode.types.forEach((type, index) => {
                if (index === 0) return;

                const prevType = typeNode.types[index - 1];
                const operator = ts.isUnionTypeNode(typeNode) ? '|' : '&';
                const startSearchPos = prevType.getEnd();
                const endSearchPos = type.getStart();

                // 使用正则精准定位操作符
                const operatorRange = code.slice(startSearchPos, endSearchPos);
                const operatorRegex = new RegExp(String.raw`(\S*)${operator}(\S*)`); // 捕获非空字符边界
                const match = operatorRange.match(operatorRegex);

                if (match) {
                    const operatorPos = match.index! + match[0].indexOf(operator);
                    const opStart = startSearchPos + operatorPos;
                    const opEnd = opStart + 1;

                    // 检查右侧是否为合法空格（允许换行）
                    const textAfter = code.slice(opEnd, opEnd + 1);
                    const validAfter = /[\s\r\n]/.test(textAfter);

                    if (!validAfter) {
                        const { line, character } = this.sourceFile.getLineAndCharacterOfPosition(opStart);
                        errors.push({
                            line: line + 1,
                            character: character + 1,
                            message: `Operator '${operator}' must be spaced.`,
                            node: node,
                            optionValue: optionValue
                        });
                    }
                }
            });
        }
        const handleUnionOrIntersectionTypeForInterface = (typeNode: ts.UnionTypeNode | ts.IntersectionTypeNode, node: ts.Node, optionValue: boolean) => {
            const operator = ts.isUnionTypeNode(typeNode) ? '|' : '&';

            // 处理每个类型节点之间的操作符
            typeNode.types.forEach((type, index) => {
                if (index === 0) return;

                const prevType = typeNode.types[index - 1];
                const startSearchPos = prevType.getEnd();
                const endSearchPos = type.getStart();
                const operatorRange = code.slice(startSearchPos, endSearchPos);

                // 精确查找操作符位置
                const operatorPos = operatorRange.indexOf(operator);
                if (operatorPos === -1) return;

                const opStart = startSearchPos + operatorPos;
                const opEnd = opStart + 1;

                // 获取操作符前后字符（包含换行符处理）
                const textBefore = code.slice(opStart - 1, opStart);
                const textAfter = code.slice(opEnd, opEnd + 1);

                // 特殊处理接口属性中的联合类型（强制要求左侧空格）
                const isInterfaceContext = typeNode.parent?.parent?.kind === ts.SyntaxKind.PropertySignature;
                const allowLeftNewline = !isInterfaceContext; // 接口属性中不允许左侧换行代替空格

                // 验证规则：
                // 1. 左侧：允许换行或空格（接口属性中不允许换行）
                // 2. 右侧：必须空格或换行
                const validBefore = allowLeftNewline ?
                    /[\s\r\n]/.test(textBefore) :
                    textBefore === ' ';

                const validAfter = /[\s\r\n]/.test(textAfter);

                if (!validBefore || !validAfter) {
                    const { line, character } = this.sourceFile.getLineAndCharacterOfPosition(opStart);
                    errors.push({
                        line: line + 1,
                        character: character + 1,
                        message: `Operator '${operator}' must be spaced.`,
                        node: node,
                        optionValue: optionValue
                    });
                }
            });
        }

        ts.forEachChild(this.sourceFile, visitNode);
        function visitNode(node: ts.Node) {
            if (ts.isBinaryExpression(node)) {
                if (node.operatorToken.kind === ts.SyntaxKind.BarToken && ts.isNumericLiteral(node.right) && node.right.text === '0') {
                    checkOperatorSpacing('|', node.operatorToken.getStart(), node.operatorToken.getEnd(), node, true);
                } else {
                    checkOperatorSpacing(node.operatorToken.getText(), node.operatorToken.getStart(), node.operatorToken.getEnd(), node);
                }
            } else if (ts.isConditionalExpression(node)) {
                checkOperatorSpacing('?', node.questionToken.getStart(), node.questionToken.getEnd(), node);
                checkOperatorSpacing(':', node.colonToken.getStart(), node.colonToken.getEnd(), node);
            } else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
                checkOperatorSpacing('=', node.operatorToken.getStart(), node.operatorToken.getEnd(), node);
            } else if (ts.isPropertyAssignment(node)) {
                // 精确查找冒号位置
                const colonRange = code.slice(node.name.end, node.initializer.getStart());
                const colonPos = colonRange.indexOf(':');
                if (colonPos !== -1) {
                    const colonStart = node.name.end + colonPos;
                    checkOperatorSpacing(':', colonStart, colonStart + 1, node);
                }
            } else if (ts.isParameter(node) && node.initializer) {
                // 精确查找等号位置
                const equalsRange = code.slice(node.name.end, node.initializer.getStart());
                const equalsPos = equalsRange.indexOf('=');
                if (equalsPos !== -1) {
                    const equalsStart = node.name.end + equalsPos;
                    checkOperatorSpacing('=', equalsStart, equalsStart + 1, node);
                }
            } else if (ts.isVariableDeclaration(node) && node.initializer) {
                const typeEnd = node.type ? node.type.getEnd() : node.name.end;
                const operatorRange = code.slice(typeEnd, node.initializer.getStart());
                const operatorPos = operatorRange.search(/=(?!>)/); // 排除=>
                if (operatorPos !== -1) {
                    const equalsStart = typeEnd + operatorPos;
                    checkOperatorSpacing('=', equalsStart, equalsStart + 1, node);
                }
            } else if (ts.isBindingElement(node) && node.initializer) {
                const equalsRange = code.slice(node.name.end, node.initializer.getStart());
                const equalsPos = equalsRange.indexOf('=');
                if (equalsPos !== -1) {
                    const equalsStart = node.name.end + equalsPos;
                    checkOperatorSpacing('=', equalsStart, equalsStart + 1, node, false, true); // 允许左侧换行
                }
            } else if (ts.isEnumMember(node) && node.initializer) {
                const operatorRange = code.slice(node.name.end, node.initializer.getStart());
                const operatorPos = operatorRange.indexOf('=');
                if (operatorPos !== -1) {
                    const equalsStart = node.name.end + operatorPos;
                    checkOperatorSpacing('=', equalsStart, equalsStart + 1, node);
                }
            } else if (ts.isPropertyDeclaration(node) && node.initializer) {
                const typeEnd = node.type ? node.type.getEnd() : node.name.end;
                const operatorRange = code.slice(typeEnd, node.initializer.getStart());
                const operatorPos = operatorRange.search(/=(?!>)/);
                if (operatorPos !== -1) {
                    const equalsStart = typeEnd + operatorPos;
                    checkOperatorSpacing('=', equalsStart, equalsStart + 1, node);
                }
            } else if (ts.isPropertySignature(node) && node.initializer) {
                checkOperatorSpacing('=', node.name.end, node.initializer.getStart(), node);
            } else if (ts.isTypeAliasDeclaration(node)) {
                handleTypeAliasDeclaration(node, int32Hint);
            } else if (ts.isConditionalTypeNode(node)) {
                // 处理条件类型中的 ? 和 :
                const afterExtends = node.extendsType.getEnd();
                const questionPos = code.indexOf('?', afterExtends);
                if (questionPos !== -1) {
                    checkOperatorSpacing('?', questionPos, questionPos + 1, node);
                }

                const afterTrueType = node.trueType.getEnd();
                const colonPos = code.indexOf(':', afterTrueType);
                if (colonPos !== -1) {
                    checkOperatorSpacing(':', colonPos, colonPos + 1, node);
                }
            } else if (ts.isUnionTypeNode(node) || ts.isIntersectionTypeNode(node)) { // 对交叉类型节点的直接处理
                handleUnionOrIntersectionType(node, node, int32Hint);
            } else if (ts.isParenthesizedTypeNode(node)) { // 增强括号类型处理
                visitNode(node.type);
                // 检查括号内可能存在的操作符（如 (A&B) 中的 &）
                handleParenthesizedOperators(node);
            } else if (ts.isInterfaceDeclaration(node)) { // 新增接口声明处理
                node.members.forEach(member => {
                    if (ts.isPropertySignature(member) && member.type) {
                        checkNestedType(member.type, node, int32Hint, true);// 特殊标记接口属性上下文
                    }
                });
            }

            ts.forEachChild(node, visitNode);
        }

        // 递归检测方法
        function checkNestedType(typeNode: ts.TypeNode, node: ts.Node, optionValue: boolean, isInterfaceContext: boolean = false) {
            if (ts.isUnionTypeNode(typeNode)) {
                handleUnionOrIntersectionTypeWithContext(typeNode, isInterfaceContext, node, optionValue);
                typeNode.types.forEach(t => checkNestedType(t, node, optionValue, isInterfaceContext));
            } else if (ts.isIntersectionTypeNode(typeNode)) {
                handleUnionOrIntersectionTypeForInterface(typeNode, node, optionValue);
                typeNode.types.forEach(t => checkNestedType(t, node, optionValue));
            } else if (ts.isParenthesizedTypeNode(typeNode)) {
                checkNestedType(typeNode.type, node, optionValue);
            }
        }

        function handleTypeAliasDeclaration(node: ts.TypeAliasDeclaration, optionValue: boolean) {
            const typeNode = node.type;
            const operatorRange = code.slice(node.name.end, typeNode.getStart());
            const operatorPos = operatorRange.indexOf('=');

            if (operatorPos !== -1) {
                const equalsStart = node.name.end + operatorPos;
                checkOperatorSpacing('=', equalsStart, equalsStart + 1, node);
            }

            // 增强：处理嵌套的联合/交叉类型
            if (ts.isUnionTypeNode(typeNode) || ts.isIntersectionTypeNode(typeNode)) {
                handleUnionOrIntersectionType(typeNode as ts.UnionTypeNode | ts.IntersectionTypeNode, node, optionValue);
            }

            if (ts.isUnionTypeNode(typeNode) || ts.isIntersectionTypeNode(typeNode)) {
                typeNode.types.forEach((type, index) => {
                    if (index === 0) return;
                    const prevType = typeNode.types[index - 1];
                    const operator = ts.isUnionTypeNode(typeNode) ? '|' : '&';
                    const operatorRange = code.slice(prevType.getEnd(), type.getStart());
                    const operatorPos = operatorRange.indexOf(operator);
                    if (operatorPos !== -1) {
                        const opStart = prevType.getEnd() + operatorPos;
                        checkOperatorSpacing(operator, opStart, opStart + 1, node);
                    }
                });
            }
        }

        // 处理括号内的操作符（如 (A&B)）
        function handleParenthesizedOperators(node: ts.ParenthesizedTypeNode) {
            // 跳过已被联合/交叉类型处理的括号
            if (ts.isUnionTypeNode(node.parent) || ts.isIntersectionTypeNode(node.parent)) return;

            const fullText = node.getText().slice(1, -1); // 去除外围括号
            const operators = ['|', '&'];

            operators.forEach(op => {
                let pos = -1;
                while ((pos = fullText.indexOf(op, pos + 1)) !== -1) {
                    // 计算在源代码中的绝对位置
                    const absolutePos = node.getStart() + pos + 1; // +1 跳过开括号
                    checkOperatorSpacing(op, absolutePos, absolutePos + 1, node);
                }
            });
        }

        return errors;
    }
    public check = (targetField: ArkFile) => {
        this.defaultOptions = this.rule && this.rule.option && this.rule.option[0] ? this.rule.option as Options : this.defaultOptions;
        const severity = this.rule.alert ?? this.metaData.severity;
        const filePath = targetField.getFilePath();
        let code = targetField.getCode();
        const myInvalidPositions = this.checkSpaceInfixOps(code, this.defaultOptions[0].int32Hint);
        const myInvalidPositionsNew = this.sortMyInvalidPositions(myInvalidPositions);
        myInvalidPositionsNew.forEach(pos => {
            this.addIssueReport(filePath, pos, severity)
        });
    }

    // 对错误位置进行排序并去重
    private sortMyInvalidPositions(myInvalidPositions: Array<{ line: number; character: number; message: string, node: ts.Node, optionValue: boolean }>) {
        // 1. 先进行排序
        myInvalidPositions.sort((a, b) => a.line - b.line || a.character - b.character);

        // 2. 使用 reduce 进行去重
        const uniqueArrays = myInvalidPositions.reduce((acc, current) => {
            const lastItem = acc[acc.length - 1];

            // 检查是否与最后一个元素的三要素相同
            if (!lastItem ||
                lastItem.line !== current.line ||
                lastItem.character !== current.character ||
                lastItem.message !== current.message) {
                acc.push(current);
            }
            return acc;
        }, [] as typeof myInvalidPositions);

        return uniqueArrays;
    }

    // 创建修复对象 
    private ruleFix(pos: number, end: number, optionValue: boolean): RuleFix {
        let textStr = '';
        let textNew = this.sourceFile.getFullText().slice(pos, end);
        textStr = textNew.trim();
        textStr = ' ' + textStr + ' ';
        return { range: [pos, end], text: textStr }
    }

    private ruleFixForTypeColumn(pos: number, end: number, optionValue: boolean): RuleFix {
        let textStr = '';
        let textNew = this.sourceFile.getFullText().slice(pos, end);
        textStr = textNew.trim();
        textStr = textStr + ' ';
        return { range: [pos, end], text: textStr }
    }

    private ruleFixForConditionalTypeNode(pos: number, end: number, optionValue: boolean): RuleFix {
        let textStr = '';
        let textNew = this.sourceFile.getFullText().slice(pos, end);
        textStr = textNew.trim();
        textStr = ' ' + textStr;
        return { range: [pos, end], text: textStr }
    }

    private addIssueReport(filePath: string, pos: { line: number, character: number, message: string, node: ts.Node, optionValue: boolean }, severity: number) {
        const fixKey = pos.line + '%' + pos.character + '%' + this.rule.ruleId;
        const mergeKey = filePath + '%' + fixKey + '%' + pos.message;
        const defect = new Defects(pos.line, pos.character, pos.message, severity, this.rule.ruleId,
            mergeKey, this.metaData.ruleDocPath, true, false, false, fixKey)

        let fix: RuleFix | undefined = undefined;
        let stPos;
        let stEnd;
        let node: ts.Node = pos.node;

        if (ts.isBinaryExpression(node)) {
            stPos = node.left.end;
            stEnd = node.right.end - node.right.getText().length;
            fix = this.ruleFix(stPos, stEnd, pos.optionValue);
        } else if (ts.isConditionalExpression(node)) {
            //? 左右加空格
            stPos = node.condition.end; //?的前后位置计算
            stEnd = node.whenTrue.end - node.whenTrue.getText().length;
            let qTextStr = this.sourceFile.getFullText().slice(stPos, stEnd);
            let qNewTextStr = ' ' + qTextStr.trim() + ' ';

            //：左右加空格
            let stFenPos = node.whenTrue.end;
            let stFenEnd = node.whenFalse.end - node.whenFalse.getText().length;
            let fenTextStr = this.sourceFile.getFullText().slice(stFenPos, stFenEnd);
            if (qTextStr == qNewTextStr || this.firstDealFlag) { //?满足条件
                //给:左右加空格
                this.firstDealFlag = false;
                fix = this.ruleFix(stFenPos, stFenEnd, pos.optionValue);
            } else {
                //给?左右加空格
                this.firstDealFlag = true;
                fix = this.ruleFix(stPos, stEnd, pos.optionValue);
            }
        } else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
        } else if (ts.isPropertyAssignment(node)) {
            stPos = node.name?.end;
            stEnd = node.initializer?.end - node.initializer?.getText().length;
            fix = this.ruleFix(stPos, stEnd, pos.optionValue);
        } else if ((ts.isParameter(node) && node.initializer) || (ts.isEnumMember(node) && node.initializer)) {
            stPos = node.name?.end;
            stEnd = node.initializer?.end - node.initializer?.getText().length;
            fix = this.ruleFix(stPos, stEnd, pos.optionValue);
        } else if (ts.isVariableDeclaration(node) && node.initializer) {
            stPos = node.name?.end;
            stEnd = node.initializer?.end - node.initializer?.getText().length;
            fix = this.ruleFix(stPos, stEnd, pos.optionValue);
        } else if (ts.isBindingElement(node) && node.initializer) {
            stPos = node.name?.end;
            stEnd = node.initializer?.end - node.initializer?.getText().length;
            fix = this.ruleFix(stPos, stEnd, pos.optionValue);
        } else if (ts.isPropertyDeclaration(node) && node.initializer) {
            if (!node.type) {
                stPos = node.name?.end;
                stEnd = node.initializer?.end - node.initializer?.getText().length;
                fix = this.ruleFix(stPos, stEnd, pos.optionValue);
            } else {
                stPos = node.type?.end;
                stEnd = node.initializer?.end - node.initializer?.getText().length;
                fix = this.ruleFix(stPos, stEnd, pos.optionValue);
            }
        } else if (ts.isPropertySignature(node) && node.initializer) {
            stPos = node.name?.end;
            stEnd = node.type ? node.type.pos : node.name.end;
            fix = this.ruleFix(stPos, stEnd, pos.optionValue);
        } else if (ts.isTypeAliasDeclaration(node)) {
            if (node.type) {
                stPos = node.name?.end;
                stEnd = node.type?.end - node.type?.getText().length;
                let textStr = this.sourceFile.getFullText().slice(stPos, stEnd);
                let textNewStr = ' ' + textStr.trim() + ' ';
                if (textStr == textNewStr || this.firstEqualsFlag) {
                    let typeNode = node.type;
                    if (ts.isUnionTypeNode(typeNode) || ts.isIntersectionTypeNode(typeNode)) {
                        if (typeNode.types.length === 2) {
                            const prevType = typeNode.types[0];
                            const nextType = typeNode.types[1];
                            const operator = ts.isUnionTypeNode(typeNode) ? '|' : '&';
                            let operatorStrNew = ' ' + operator + ' ';
                            let textNew = this.sourceFile.getFullText().slice(prevType.getEnd(), nextType.getStart());
                            let operatorStart = prevType.getEnd();
                            let operatorEnd = nextType.getStart();
                            if (operatorStrNew != textNew) {
                                this.firstEqualsFlag = false;
                                fix = this.ruleFix(operatorStart, operatorEnd, pos.optionValue);
                            }
                        } else if (typeNode.types.length === 3) {
                            const prevType = typeNode.types[0];
                            const nextType = typeNode.types[1];
                            const lastType = typeNode.types[2];
                            const operator = ts.isUnionTypeNode(typeNode) ? '|' : '&';
                            let operatorStrNew = operator + ' ';
                            let firstTextStr = this.sourceFile.getFullText().slice(typeNode.getStart(), prevType.getStart());
                            let secondTextStr = this.sourceFile.getFullText().slice(prevType.getEnd(), nextType.getStart());
                            let threeTextStr = this.sourceFile.getFullText().slice(nextType.getEnd(), lastType.getStart());
                            let operatorStrLastNew = ' ' + operator + ' ';
                            if (firstTextStr == '') {
                                if (this.countTypeColumnFlag == 0 && secondTextStr != '' && secondTextStr != operatorStrLastNew) {
                                    let operatorStart = prevType.getEnd();
                                    let operatorEnd = nextType.getStart();
                                    this.countTypeColumnFlag = 2;
                                    fix = this.ruleFix(operatorStart, operatorEnd, pos.optionValue);
                                } else if (this.countTypeColumnFlag == 2 && threeTextStr != '' && threeTextStr != operatorStrLastNew) {
                                    let operatorStart = nextType.getEnd();
                                    let operatorEnd = lastType.getStart();
                                    this.countTypeColumnFlag = 0;
                                    this.firstEqualsFlag = false;
                                    fix = this.ruleFix(operatorStart, operatorEnd, pos.optionValue);
                                }
                            } else {
                                if (firstTextStr != operatorStrNew && this.countTypeColumnFlag == 0) {
                                    this.countTypeColumnFlag = 1;
                                    fix = this.ruleFixForTypeColumn(typeNode.getStart(), prevType.getStart(), pos.optionValue);
                                } else if (this.countTypeColumnFlag == 1 && secondTextStr != '' && secondTextStr != operatorStrLastNew) {
                                    let operatorStart = prevType.getEnd();
                                    let operatorEnd = nextType.getStart();
                                    this.countTypeColumnFlag = 2;
                                    fix = this.ruleFix(operatorStart, operatorEnd, pos.optionValue);
                                } else if (this.countTypeColumnFlag == 2 && threeTextStr != '' && threeTextStr != operatorStrLastNew) {
                                    let operatorStart = nextType.getEnd();
                                    let operatorEnd = lastType.getStart();
                                    this.countTypeColumnFlag = 0;
                                    this.firstEqualsFlag = false;
                                    fix = this.ruleFix(operatorStart, operatorEnd, pos.optionValue);
                                }
                            }
                        }
                    }
                } else if (textStr.includes('=\r\n')) {
                    let typeNode = node.type;
                    if (ts.isUnionTypeNode(typeNode) || ts.isIntersectionTypeNode(typeNode)) {
                        const operator = ts.isUnionTypeNode(typeNode) ? '|' : '&';
                        // 首字符操作符检测
                        if (typeNode.types.length > 0) {
                            const firstType = typeNode.types[0];
                            const startPos = typeNode.getStart();
                            const firstTypeStart = firstType.getStart();
                            const leadingRange = this.sourceFile.getFullText().slice(startPos, firstTypeStart);
                            let leadingRangeNew = leadingRange.trim() + ' '; // | 变成 |+' '
                            if (leadingRange != leadingRangeNew) {
                                fix = this.ruleFixForTypeColumn(startPos, firstTypeStart, pos.optionValue);
                            }
                        }
                    }
                } else {
                    const typeNode = node.type as ts.UnionTypeNode | ts.IntersectionTypeNode;
                    if (typeNode.types.length === 2) {
                        const prevType = typeNode.types[0];
                        const nextType = typeNode.types[1];
                        const operator = ts.isUnionTypeNode(typeNode) ? '|' : '&';
                        let operatorStrNew = ' ' + operator + ' ';
                        let textNew = this.sourceFile.getFullText().slice(prevType.getEnd(), nextType.getStart());
                        if (operatorStrNew != textNew) {
                            this.firstEqualsFlag = true;
                        } else {
                            this.firstEqualsFlag = false;
                            let equTextStr = this.sourceFile.getFullText().slice(node.name.end, typeNode.getStart());
                            let equTextNewStr = ' ' + equTextStr.trim() + ' ';
                            if (equTextStr != equTextNewStr) {
                                fix = this.ruleFix(node.name.end, typeNode.getStart(), pos.optionValue);
                            }
                        }
                    } else if (typeNode.types.length > 2) {
                        const prevType = typeNode.types[0];
                        const nextType = typeNode.types[1];
                        const lastType = typeNode.types[2];
                        const operator = ts.isUnionTypeNode(typeNode) ? '|' : '&';
                        let operatorStrNew = ' ' + operator + ' ';
                        let equTextStr = this.sourceFile.getFullText().slice(node.name.end, typeNode.getStart());
                        let equTextNewStr = ' ' + equTextStr.trim() + ' ';
                        let firstTextStr = this.sourceFile.getFullText().slice(typeNode.getStart(), prevType.getStart());
                        let secondTextStr = this.sourceFile.getFullText().slice(prevType.getEnd(), nextType.getStart());
                        let threeTextStr = this.sourceFile.getFullText().slice(nextType.getEnd(), lastType.getStart());
                        let x = firstTextStr.trim() + ' ';
                        let y = ' ' + secondTextStr.trim() + ' ';
                        let z = ' ' + threeTextStr.trim() + ' ';
                        if (equTextStr != equTextNewStr && !this.specialTypeAliasDeclarationFlag) {
                            if (firstTextStr != '') {
                                if (firstTextStr != x || secondTextStr != y || threeTextStr != z) {
                                    this.specialTypeAliasDeclarationFlag = true;
                                } else {
                                    this.specialTypeAliasDeclarationFlag = false;
                                }
                            } else {
                                if (secondTextStr != y || threeTextStr != z) {
                                    this.specialTypeAliasDeclarationFlag = true;
                                } else {
                                    this.specialTypeAliasDeclarationFlag = false;
                                }
                            }
                            fix = this.ruleFix(node.name.end, typeNode.getStart(), pos.optionValue);
                        } else {
                            if (firstTextStr != '') {
                                if (firstTextStr != operatorStrNew && this.countTypeColumnFlag == 0) {
                                    this.countTypeColumnFlag = 1;
                                    fix = this.ruleFixForTypeColumn(typeNode.getStart(), prevType.getStart(), pos.optionValue);
                                } else if (this.countTypeColumnFlag == 1 && secondTextStr != '' && secondTextStr != operatorStrNew) {
                                    let operatorStart = prevType.getEnd();
                                    let operatorEnd = nextType.getStart();
                                    this.countTypeColumnFlag = 2;
                                    fix = this.ruleFix(operatorStart, operatorEnd, pos.optionValue);
                                } else if (this.countTypeColumnFlag == 2 && threeTextStr != '' && threeTextStr != operatorStrNew) {
                                    let operatorStart = nextType.getEnd();
                                    let operatorEnd = lastType.getStart();
                                    this.countTypeColumnFlag = 0;
                                    this.firstEqualsFlag = false;
                                    this.specialTypeAliasDeclarationFlag = false;
                                    fix = this.ruleFix(operatorStart, operatorEnd, pos.optionValue);
                                }
                            } else {
                                if (this.countTypeColumnFlag == 0 && secondTextStr != '' && secondTextStr != y) {
                                    let operatorStart = prevType.getEnd();
                                    let operatorEnd = nextType.getStart();
                                    this.countTypeColumnFlag = 2;
                                    fix = this.ruleFix(operatorStart, operatorEnd, pos.optionValue);
                                } else if (this.countTypeColumnFlag == 2 && threeTextStr != '' && threeTextStr != z) {
                                    let operatorStart = nextType.getEnd();
                                    let operatorEnd = lastType.getStart();
                                    this.countTypeColumnFlag = 0;
                                    this.firstEqualsFlag = false;
                                    this.specialTypeAliasDeclarationFlag = false;
                                    fix = this.ruleFix(operatorStart, operatorEnd, pos.optionValue);
                                }
                            }
                        }
                    }
                }
            }
        } else if (ts.isConditionalTypeNode(node)) {
            stPos = node.extendsType.getEnd();
            stEnd = node.trueType.getStart();
            let queStr = this.sourceFile.getFullText().slice(stPos, stEnd);
            if (!queStr.includes('?\r\n') && !queStr.startsWith('\r\n')) {
                let queNewStr = ' ' + queStr.trim() + ' ';
                let stStart = node.trueType.getEnd();
                let stLast = node.falseType.getStart();
                let maoStr = this.sourceFile.getFullText().slice(stStart, stLast);
                let maoNewStr = ' ' + maoStr.trim() + ' ';
                if (queStr != queNewStr && !this.isConditionalTypeFlag) {
                    if (maoStr != maoNewStr) {
                        this.isConditionalTypeFlag = true;
                    } else {
                        this.isConditionalTypeFlag = false;
                    }
                    fix = this.ruleFix(stPos, stEnd, pos.optionValue);
                } else {
                    if (maoStr != maoNewStr) {
                        this.isConditionalTypeFlag = false;
                        fix = this.ruleFix(stStart, stLast, pos.optionValue);
                    }
                }
            } else if (queStr.startsWith('\r\n')) {
                let speStartPos = node.extendsType.getEnd();
                let speTrueStart = node.trueType.getStart();
                let speTrueEnd = node.trueType.getEnd();
                let speFalseStart = node.falseType.getStart();
                let aStr = this.sourceFile.getFullText().slice(speStartPos, speTrueStart);
                let bStr = this.sourceFile.getFullText().slice(speTrueEnd, speFalseStart);
                if (aStr.startsWith('\r\n') && aStr.endsWith('?') && !this.isConditionalTypeFlag) {
                    this.isConditionalTypeFlag = true;
                    fix = this.ruleFixForTypeColumn(speTrueStart - 1, speTrueStart, pos.optionValue)
                } else if (bStr.startsWith(':') && bStr.includes('\r\n')) {
                    this.isConditionalTypeFlag = false;
                    fix = this.ruleFixForConditionalTypeNode(speTrueEnd, speTrueEnd + 1, pos.optionValue)
                }
            } else {
                //'?\r\n  '
                let xPos = node.extendsType.getEnd();
                let stStart = node.trueType.getEnd();
                let stLast = node.falseType.getStart();
                let maoStr = this.sourceFile.getFullText().slice(stStart, stLast);
                let maoNewStr = ' ' + maoStr.trim() + ' ';
                if (!queStr.startsWith(' ') && !this.isConditionalTypeFlag) {
                    if (maoStr != maoNewStr) {
                        this.isConditionalTypeFlag = true;
                    } else {
                        this.isConditionalTypeFlag = false;
                    }
                    fix = this.ruleFixForConditionalTypeNode(xPos, xPos + 1, pos.optionValue);
                } else {
                    if (maoStr != maoNewStr && !maoStr.includes('\r\n')) {
                        this.isConditionalTypeFlag = false;
                        fix = this.ruleFix(stStart, stLast, pos.optionValue);
                    } else {
                        let topMaoFlag = maoStr.startsWith(':');
                        let endMaoFlag = maoStr.endsWith(':');
                        if (!maoStr.includes('\r\n')) {
                            this.isConditionalTypeFlag = false;
                            fix = this.ruleFixForConditionalTypeNode(stStart, stLast, pos.optionValue);
                        } else {
                            if (topMaoFlag) {
                                this.isConditionalTypeFlag = false;
                                fix = this.ruleFix(node.trueType.getEnd(), node.trueType.getEnd() + 1, pos.optionValue);
                            } else {
                                this.isConditionalTypeFlag = false;
                                fix = this.ruleFixForTypeColumn(node.falseType.getStart() - 1, node.falseType.getStart(), pos.optionValue);
                            }
                        }
                    }
                }
            }
        } else if (ts.isUnionTypeNode(node) || ts.isIntersectionTypeNode(node)) { // 对交叉类型节点的直接处理
            if (node.types.length > 1) {
                const firstType = node.types[0];
                const netxType = node.types[1];
                const leadingRange = this.sourceFile.getFullText().slice(firstType.getEnd(), netxType.getStart());
                let leadingRangeNew = ' ' + leadingRange.trim() + ' '; // | 变成 |+' '
                if (leadingRange != leadingRangeNew) {
                    fix = this.ruleFix(firstType.getEnd(), netxType.getStart(), pos.optionValue);
                }
            }
        } else if (ts.isParenthesizedTypeNode(node)) { // 增强括号类型处理
        } else if (ts.isInterfaceDeclaration(node)) { // 新增接口声明处理
            // 遍历接口的所有成员
            node.members.forEach(member => {
                if (ts.isPropertySignature(member) && member.type && ts.isUnionTypeNode(member.type)) {
                    const typeNode = member.type;
                    typeNode.types.forEach((type, index) => {
                        if (index === 0) return; // 跳过第一个类型
                        const prevType = typeNode.types[index - 1];  // 获取前一个类型
                        const currentType = type;                    // 当前类型

                        // 获取两个类型之间的文本（包含操作符）
                        const startPos = prevType.getEnd();
                        const endPos = currentType.getStart();
                        const operatorRange = this.sourceFile.getFullText().slice(startPos, endPos);
                        let operatorRangeNew = ' ' + operatorRange.trim() + ' ';
                        let beFlag = operatorRange.startsWith(' ');
                        let afFlag = operatorRange.endsWith(' ');
                        if (operatorRange != operatorRangeNew && !beFlag && afFlag) {
                            fix = this.ruleFix(startPos, endPos, pos.optionValue);
                        } else if (operatorRange != operatorRangeNew && beFlag && !afFlag) {
                            fix = this.ruleFix(startPos, endPos, pos.optionValue);
                        }
                    });
                }
            });
        }

        this.issues.push(new IssueReport(defect, fix));
        RuleListUtil.push(defect);
    }
}